home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / pisces / mkdepend / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  13.3 KB  |  674 lines

  1. /*
  2.  * $XConsortium: main.c,v 1.33 89/07/21 11:35:21 jim Exp $
  3.  */
  4. #include "def.h"
  5. #ifdef hpux
  6. #define sigvec sigvector
  7. #endif /* hpux */
  8.  
  9. #include <signal.h>
  10. #include <errno.h>
  11. #ifdef VMS
  12. #include <unixio.h>
  13. #endif
  14.  
  15. #ifdef DEBUG
  16. int    debug;
  17. #endif
  18.  
  19. /**
  20.  ** MODIFIED: 06/25/90 by MBN
  21.  **
  22.  ** Added the -X option to generate dependencies for a file but *not* an RCS
  23.  ** dependency. This is useful for LEX and YACC generated files that have 
  24.  ** include statements, but whose source is machine-produced.
  25.  **/
  26.  
  27. /**
  28.  ** MODIFIED: 06/13/90 by MBN
  29.  **
  30.  ** Modified basename() function to check extensions and added SourceExtensions 
  31.  ** array of valid source filename extensions.
  32.  **/
  33.  
  34. /**
  35.  ** MODIFIED: 06/08/90 by MBN
  36.  **
  37.  ** Add a dependency to automatically link each header file when checkout
  38.  ** out to the project include directory if the command line option -L 
  39.  ** is specified
  40.  **/
  41.  
  42. /**
  43.  ** MODIFIED: 05/16/90 by MBN
  44.  **
  45.  ** Add a dependency for each file in the file list on the command line to
  46.  ** its RCS master of the form "foo.h :: $(RCSDIR)foo.h$(RCSEXT)" if the
  47.  ** command line option -R (for RCS) is specified
  48.  **/
  49.  
  50. /**
  51.  ** MODIFIED: 05/14/90 by MBN
  52.  **
  53.  ** If the extension on a file is .l, .y, .h, .c, or .C don't zap it! This 
  54.  ** allows mkdepend to calculate dependencies for files contained in the SRCS
  55.  ** list in the Imake file. If this is not done, then "foo.h" becomes "foo.o"
  56.  **/
  57.  
  58. /**
  59.  ** MODIFIED: 05/11/90 by MBN
  60.  **
  61.  ** Removed hard-coded path separator character and changed to a user-defined
  62.  ** character constant. The symbol PATHSEP defaults to '/' but can be over
  63.  ** ridden on the command line to mkdepend.
  64.  **/
  65.  
  66. char path_sep = PATHSEP;
  67. /* The following is used to find the end of the directory information.  In
  68.    UNIX, it is '/'; in VMS, however, it is ']', which differs from the path
  69.    separator '.'.
  70.    */
  71. char path_end = PATHSEP;
  72.  
  73. char *ProgramName;
  74.  
  75. char    *directives[] = {
  76.     "if",
  77.     "ifdef",
  78.     "ifndef",
  79.     "else",
  80.     "endif",
  81.     "define",
  82.     "undef",
  83.     "include",
  84.     "line",
  85.     "pragma",
  86.     "error",
  87.     "ident",
  88.     "sccs",
  89.     "elif",
  90.     "eject",
  91.     NULL
  92. };
  93.  
  94. /**
  95.  ** SourceExtensions contains the extensions for files that have conversion
  96.  ** rules, that is, get transposed from one type of "thing" to another. Any
  97.  ** file passed on the command line that does *NOT* have one of these extensions
  98.  ** is assumed to be a miscellaneous file and, if the -R (RCS Checkout) flag
  99.  ** is provided, will result in a dependency added for to check out the file
  100.  ** from under RCS control.
  101.  **/
  102.  
  103. char *SourceExtensions[] = {
  104.     "h",
  105.     "hxx",
  106.     "c",
  107.     "cxx",
  108.     "C",
  109.     "y",
  110.     "Y",
  111.     "l",
  112.     "L",
  113.     NULL
  114. };
  115.  
  116. struct symtab    predefs[] = {
  117. #ifdef apollo
  118.     {"apollo", NULL},
  119. #endif
  120. #ifdef ibm032
  121.     {"ibm032", NULL},
  122. #endif
  123. #ifdef sun
  124.     {"sun", NULL},
  125. #endif
  126. #ifdef os2
  127.     {"os2", NULL},
  128. #endif
  129. #ifdef DOS
  130.     {"DOS", NULL},
  131. #endif
  132. #ifdef hpux
  133.     {"hpux", NULL},
  134. #endif
  135. #ifdef vax
  136.     {"vax", NULL},
  137. #endif
  138. #ifdef VMS
  139.     {"VMS", NULL},
  140. #endif
  141. #ifdef cray
  142.     {"cray", NULL},
  143. #endif
  144. #ifdef CRAY
  145.     {"CRAY", NULL},
  146. #endif
  147. #ifdef att
  148.     {"att", NULL},
  149. #endif
  150. #ifdef mips
  151.     {"mips", NULL},
  152. #endif
  153. #ifdef ultrix
  154.     {"ultrix", NULL},
  155. #endif
  156. #ifdef mc68000
  157.     {"mc68000", NULL},
  158. #endif
  159. #ifdef mc68020
  160.     {"mc68020", NULL},
  161. #endif
  162. #ifdef __GNUC__
  163.     {"__GNUC__", NULL},
  164. #endif
  165. #ifdef __STDC__
  166.     {"__STDC__", NULL},
  167. #endif
  168.     {NULL, NULL}
  169. };
  170.  
  171. struct symtab    deflist[ MAXDEFINES ];
  172. struct    inclist inclist[ MAXFILES ],
  173.         *inclistp = inclist;
  174.  
  175. char    *filelist[ MAXFILES ];
  176. char    *dependonlylist[ MAXFILES ];
  177. char    *includedirs[ MAXDIRS ];
  178. char    *notdotdot[ MAXDIRS ];
  179. char    *objfile = ".o";
  180. char    *startat = "# DO NOT DELETE THIS LINE -- mkdepend depends on it.";
  181. int    width = 78;
  182. boolean    printed = FALSE;
  183. boolean    verbose = FALSE;
  184. boolean    show_where_not = FALSE;
  185. boolean rcs_dependency = FALSE;
  186. boolean link_dependency = FALSE;
  187.  
  188. void redirect();
  189.  
  190. static
  191. #ifdef SIGNALRETURNSINT
  192. int
  193. #else
  194. void
  195. #endif
  196. catch (sig)
  197.     int sig;
  198. {
  199.     fflush (stdout);
  200.     log_fatal ("got signal %d\n", sig);
  201. }
  202.  
  203. #ifndef os2
  204. #ifndef USG
  205. struct sigvec sig_vec = {
  206.     catch,
  207.      (1<<(SIGINT -1))
  208.     |(1<<(SIGQUIT-1))
  209.     |(1<<(SIGBUS-1))
  210.     |(1<<(SIGILL-1))
  211.     |(1<<(SIGSEGV-1))
  212.     |(1<<(SIGHUP-1))
  213.     |(1<<(SIGPIPE-1))
  214.     |(1<<(SIGSYS-1)),
  215.     0
  216. };
  217. #endif /* USG */
  218. #endif /* os2 */
  219.  
  220. main(argc, argv)
  221.     int    argc;
  222.     char    **argv;
  223. {
  224.     register struct symtab    *symp = deflist;
  225.     register char    **fp = filelist;
  226.     register char    **incp = includedirs;
  227.     register char    **temp;
  228.     register char    **dp = dependonlylist;
  229.     register char    *p;
  230.     register struct inclist    *ip;
  231.     char    *makefile = NULL;
  232.     struct filepointer    *filecontent;
  233.     struct symtab *psymp = predefs;
  234.     char *endmarker = NULL;
  235.     char buf[ 2 ];
  236.  
  237.     ProgramName = argv[0];
  238.  
  239.     while (psymp->s_name)
  240.         *symp++ = *psymp++;
  241.     for(argc--, argv++; argc; argc--, argv++) {
  242.             /* if looking for endmarker then check before parsing */
  243.         if (endmarker && strcmp (endmarker, *argv) == 0) {
  244.             endmarker = NULL;
  245.             continue;
  246.         }
  247.         if (**argv != '-') {
  248.             /* scan existing filenames and only add to list if
  249.                this new one has not already been specified */
  250.             for (temp = filelist; *temp; temp++)
  251.                 if(strcmp(argv[0],*temp) == 0)
  252.                 break;
  253.             if (*temp == NULL)
  254.                 *fp++ = argv[0];
  255.             continue;
  256.         }
  257.         switch(argv[0][1]) {
  258.         case '-':
  259.             endmarker = &argv[0][2];
  260.             if (endmarker[0] == '\0') endmarker = "--";
  261.             break;
  262.         case 'D':
  263.             symp->s_name = argv[0]+2;
  264.             if (*symp->s_name == '\0') {
  265.                 symp->s_name = *(++argv);
  266.                 argc--;
  267.             }
  268.             for (p=symp->s_name; *p ; p++)
  269.                 if (*p == '=') {
  270.                     *p++ = '\0';
  271.                     break;
  272.                 }
  273.             symp->s_value = p;
  274.             symp++;
  275.             break;
  276.         case 'R':
  277.             rcs_dependency = TRUE;
  278.             break;
  279.         case 'L':
  280.             link_dependency = TRUE;
  281.             break;
  282.               case 'X':
  283.             if(argv[0][2] != ' ' && argv[0][2] != '\0')
  284.             {
  285.                 *dp++ = &(argv[0][2]);
  286.                 *fp++ = &(argv[0][2]);
  287.             }
  288.             break;
  289.         case 'I':
  290.             *incp++ = argv[0]+2;
  291.             if (**(incp-1) == '\0') {
  292.                 *(incp-1) = *(++argv);
  293.                 argc--;
  294.             }
  295.             break;
  296.         /* do not use if endmarker processing */
  297.         case 'w':
  298.             if (endmarker) break;
  299.             if (argv[0][2] == '\0') {
  300.                 argv++;
  301.                 argc--;
  302.                 width = atoi(argv[0]);
  303.             } else
  304.                 width = atoi(argv[0]+2);
  305.             break;
  306.         case 'o':
  307.             if (endmarker) break;
  308.             if (argv[0][2] == '\0') {
  309.                 argv++;
  310.                 argc--;
  311.                 objfile = argv[0];
  312.             } else
  313.                 objfile = argv[0]+2;
  314.             break;
  315.         case 'v':
  316.             if (endmarker) break;
  317.             verbose = TRUE;
  318. #ifdef DEBUG
  319.             if (argv[0][2])
  320.                 debug = atoi(argv[0]+2);
  321. #endif
  322.             break;
  323.         case 's':
  324.             if (endmarker) break;
  325.             startat = argv[0]+2;
  326.             if (*startat == '\0') {
  327.                 startat = *(++argv);
  328.                 argc--;
  329.             }
  330.             if (*startat != '#')
  331.                 log_fatal("-s flag's value should start %s\n",
  332.                     "with '#'.");
  333.             break;
  334.         case 'f':
  335.             if (endmarker) break;
  336.             makefile = argv[0]+2;
  337.             if (*makefile == '\0') {
  338.                 makefile = *(++argv);
  339.                 argc--;
  340.             }
  341.             break;
  342.  
  343.         case 'P':    /* User-specified path separator character */
  344.             if( argv[0][2] == '\0' || argv[0][2] == ' ')
  345.                 log_fatal("invalid pathname separator specified\n");
  346.             path_sep = argv[0][2];
  347.             break;
  348.                     
  349.         case 'Q':    /* User-specified path end character */
  350.             path_end = argv[0][2];
  351.             break;
  352.                     
  353.         /* Ignore -O, -g so we can just pass ${CFLAGS} to
  354.            makedepend
  355.          */
  356.         case 'O':
  357.         case 'g':
  358.             break;
  359.         default:
  360.             if (endmarker) break;
  361.     /*        log_fatal("unknown opt = %s\n", argv[0]); */
  362.             do_log("ignoring option %s\n", argv[0]);
  363.         }
  364.     }
  365.  
  366.     redirect(startat, makefile);
  367.  
  368.     /*
  369.      * catch signals.
  370.      */
  371. #ifdef USG
  372. /*  should really reset SIGINT to SIG_IGN if it was.  */
  373.     signal (SIGHUP, catch);
  374.     signal (SIGINT, catch);
  375.     signal (SIGQUIT, catch);
  376.     signal (SIGILL, catch);
  377.     signal (SIGBUS, catch);
  378.     signal (SIGSEGV, catch);
  379.     signal (SIGSYS, catch);
  380. #else
  381. #ifndef os2
  382.     sigvec(SIGHUP, &sig_vec, (struct sigvec *)0);
  383.     sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
  384.     sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
  385.     sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
  386.     sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
  387.     sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
  388.     sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
  389. #endif
  390. #endif
  391.  
  392.     /*
  393.      * now peruse through the list of files.
  394.      */
  395.     for(fp=filelist; *fp; fp++) {
  396.         if(is_source_file(*fp)) {
  397.         filecontent = getfile(*fp);
  398.         ip = newinclude(*fp, (char *)NULL);
  399.         find_includes(filecontent, ip, ip, 0);
  400.         freefile(filecontent);
  401.         recursive_pr_include(ip, ip->i_file, *fp);
  402.         }
  403.  
  404.         if(is_depend_only_file(*fp) == TRUE) {
  405.         sprintf(buf, "\n");
  406.         fwrite(buf, strlen(buf), 1, stdout);
  407.         }
  408.         else if(rcs_dependency == TRUE) {
  409.         rcs_pr(*fp, "$(RCSDIR)", "$(RCSEXT)");
  410.         if (link_dependency == TRUE)
  411.             link_pr(*fp);
  412.         }
  413.         inc_clean();
  414.     }
  415.     if (printed)
  416.         printf("\n");
  417.     exit(0);
  418. }
  419.  
  420. int is_source_file(file)
  421.     register char    *file;
  422. {
  423.     register char    *p, **q;
  424.  
  425.     for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
  426.  
  427.     if (*p == path_sep)
  428.         p++;
  429.  
  430.     file = copy(p);
  431.     for(p=file+strlen(file); p>file && *p != '.'; p--) ;
  432.  
  433.     if (*p == '.')
  434.     {
  435.         for( q = SourceExtensions; *q; q++)
  436.         if( !strcmp(*q, (p+1)) )
  437.         {
  438.         return 1;
  439.         }
  440.     }
  441.     return 0;
  442. }
  443.  
  444. int is_depend_only_file(file)
  445.     register char    *file;
  446. {
  447.     register char    *p, **q;
  448.  
  449.     for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
  450.  
  451.     if (*p == path_sep)
  452.         p++;
  453.  
  454.     for( q = dependonlylist; *q; q++)
  455.     if( !strcmp(*q, p) )
  456.         return 1;
  457.     return 0;
  458. }
  459.  
  460. struct filepointer *getfile(file)
  461.     char    *file;
  462. {
  463.     register int    i;
  464.     struct filepointer    *content;
  465.     struct stat    st;
  466.     FILE   *fd;
  467.  
  468.     content = (struct filepointer *)malloc(sizeof(struct filepointer));
  469.     if ((fd = fopen(file, "r")) == NULL) {
  470.         do_log("cannot open \"%s\" [errno=%d]\n", file, errno);
  471.         content->f_p = content->f_base = content->f_end = malloc(1);
  472.         *content->f_p = '\0';
  473.         return(content);
  474.     }
  475.     stat(file, &st);
  476.     content->f_len = st.st_size+1;
  477.     content->f_base = malloc(content->f_len);
  478.     if (content->f_base == NULL)
  479.       log_fatal("cannot allocate mem\n");
  480.     for (i = 0; i < st.st_size; ++i)
  481.       content->f_base[i] = getc (fd);
  482.     fclose(fd);
  483.     content->f_p = content->f_base;
  484.     content->f_end = content->f_base + st.st_size;
  485.     *content->f_end = '\0';
  486.     content->f_line = 0;
  487.     return(content);
  488. }
  489.  
  490. freefile(fp)
  491.     struct filepointer    *fp;
  492. {
  493.     free(fp->f_base);
  494.     free(fp);
  495. }
  496.  
  497. /*VARARGS*/
  498. log_fatal(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
  499. char* x0;
  500. {
  501.     do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
  502.     exit (1);
  503. }
  504.  
  505. /*VARARGS0*/
  506. do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
  507. char* x0;
  508. {
  509.     fprintf(stderr, "%s:  ", ProgramName);
  510.     fprintf(stderr, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
  511. }
  512.  
  513. char *copy(str)
  514.     register char    *str;
  515. {
  516.     register char    *p = malloc(strlen(str) + 1);
  517.  
  518.     strcpy(p, str);
  519.     return(p);
  520. }
  521.  
  522. match(str, list)
  523.     register char    *str, **list;
  524. {
  525.     register int    i;
  526.  
  527.     for (i=0; *list; i++, list++)
  528.         if (strcmp(str, *list) == 0)
  529.             return(i);
  530.     return(-1);
  531. }
  532.  
  533. /*
  534.  * Get the next line.  We only return lines beginning with '#' since that
  535.  * is all this program is ever interested in.
  536.  */
  537. char *getline(filep)
  538.     register struct filepointer    *filep;
  539. {
  540.     register char    *p,    /* walking pointer */
  541.             *eof,    /* end of file pointer */
  542.             *bol;    /* beginning of line pointer */
  543.     register    lineno;    /* line number */
  544.  
  545.     p = filep->f_p;
  546.     eof = filep->f_end;
  547.     if (p >= eof)
  548.         return((char *)NULL);
  549.     lineno = filep->f_line;
  550.  
  551.     for(bol = p--; ++p < eof; ) {
  552.         if (*p == '/' && *(p+1) == '*') { /* consume comments */
  553.             *p++ = ' ', *p++ = ' ';
  554.             while (*p) {
  555.                 if (*p == '*' && *(p+1) == '/') {
  556.                     *p++ = ' ', *p = ' ';
  557.                     break;
  558.                 }
  559.                 else if (*p == '\n')
  560.                     lineno++;
  561.                 *p++ = ' ';
  562.             }
  563.             continue;
  564.         }
  565.         else if (*p == '\n') {
  566.             lineno++;
  567.             if (*bol == '#') {
  568.                 register char *cp;
  569.  
  570.                 *p++ = '\0';
  571.                 /* punt lines with just # (yacc generated) */
  572.                 for (cp = bol+1; 
  573.                      *cp && (*cp == ' ' || *cp == '\t'); cp++);
  574.                 if (*cp) goto done;
  575.             }
  576.             bol = p+1;
  577.         }
  578.     }
  579.     if (*bol != '#')
  580.         bol = NULL;
  581. done:
  582.     filep->f_p = p;
  583.     filep->f_line = lineno;
  584.     return(bol);
  585. }
  586.  
  587. #ifdef VMS
  588. void unlink (name)
  589.      char *name;
  590. {
  591.   char command[200];
  592.   /* Use the DELETE command (executed through SYSTEM), since VMS does not
  593.      support UNLINK */
  594.   sprintf (command, "delete %s;", name);
  595.   system (command);
  596. }
  597. #endif
  598.  
  599. #ifdef USG
  600. int rename (from, to)
  601.     char *from, *to;
  602. {
  603.     (void) unlink (to);
  604.     if (link (from, to) == 0) {
  605.     unlink (from);
  606.     return 0;
  607.     } else {
  608.     return -1;
  609.     }
  610. }
  611. #endif /* USG */
  612.  
  613. void
  614. redirect(line, makefile)
  615.     char    *line,
  616.         *makefile;
  617. {
  618.     struct stat    st;
  619.     FILE    *fdin, *fdout;
  620.     char    backup[ BUFSIZ ],
  621.         buf[ BUFSIZ ];
  622.     boolean    found = FALSE;
  623.     int    len;
  624.  
  625.     /*
  626.      * if makefile is "-" then let it pour onto stdout.
  627.      */
  628.     if (makefile && *makefile == '-' && *(makefile+1) == '\0')
  629.         return;
  630.  
  631.     /*
  632.      * use a default makefile is not specified.
  633.      */
  634.     if (!makefile) {
  635.         if (stat("makefile", &st) == 0)
  636.             makefile = "makefile";
  637.         else if (stat("Makefile", &st) == 0)
  638.             makefile = "Makefile";
  639.         else
  640.             log_fatal("[mM]akefile is not present\n");
  641.     }
  642.     else
  643.         stat(makefile, &st);
  644.     if ((fdin = fopen(makefile, "r")) == NULL)
  645.         log_fatal("cannot open \"%s\"\n", makefile);
  646.     sprintf(backup, "%s.bak", makefile);
  647.     unlink(backup);
  648.     fclose(fdin);
  649.     if (rename(makefile, backup) < 0)
  650.         log_fatal("cannot rename %s to %s\n", makefile, backup);
  651.     fdin = fopen(backup, "r");
  652.     if ((fdout = freopen(makefile, "w", stdout)) == NULL)
  653.         log_fatal("cannot open \"%s\"\n", backup);
  654.     len = strlen(line);
  655.     while (fgets(buf, BUFSIZ, fdin) && !found) {
  656.         if (*buf == '#' && strncmp(line, buf, len) == 0)
  657.             found = TRUE;
  658.         fputs(buf, fdout);
  659.     }
  660.     if (!found) {
  661.         if (verbose)
  662.         do_log("Adding new delimiting line \"%s\" and dependencies...\n",
  663.             line);
  664.         puts(line); /* same as fputs(fdout); but with newline */
  665.     }
  666.     fflush(fdout);
  667. #ifdef USG
  668.     chmod(makefile, st.st_mode);
  669. #else
  670. /*        fchmod(fileno(fdout), st.st_mode); */
  671.         chmod(makefile, st.st_mode);
  672. #endif /* USG */
  673. }
  674.